home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / DISK / CSAP312.ARJ / SORTDIR.C < prev    next >
C/C++ Source or Header  |  1991-12-16  |  10KB  |  397 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <conio.h>
  5. #include <dos.h>
  6. #include <ctype.h>
  7. #include <mem.h>
  8. #include <alloc.h>
  9.  
  10. #include "dosstruc.h"
  11.  
  12. /*---   Function Prototypes   ---*/
  13.  
  14. int             SearchFirst (struct ExtFcb * Fcb);
  15. int             AbortProgram (void);
  16. int             isdevice (int handle);
  17. void            ReadRoot (void);
  18. void            ReadSub (void);
  19. void            WriteRoot (void);
  20. void            WriteSub (void);
  21. long            Alu2Sec (struct DpbStruct * Dpb, unsigned Alu);
  22. char           *strrspn (char *s1, char *s2);
  23. void            PutQueue (struct ClusterQueue * Q, unsigned Cluster);
  24. unsigned        NextCl (int Is12Bit, unsigned Cluster, unsigned char *Fat);
  25. void            FreeCluster (int Is12Bit, unsigned Val, unsigned Cluster, unsigned char Fat[]);
  26.  
  27. /*---  End of Prototypes  ---*/
  28.  
  29.  
  30. /*
  31.  * SORTDIR is the main routine of CSAP.  It is a recursive routine that will
  32.  * walk the directory hierarchy, sorting all directories that it finds.  It
  33.  * uses the quick sort or quicker sort algorithm provided by most C runtime
  34.  * libraries to perform the actual sort.  It uses DOS Int 25H and 26H,
  35.  * Absolute Disk Read and Absolute Disk Write, to read the directories into
  36.  * memory for sorting and to write out the sorted directories.  It depends
  37.  * upon information about the physical characteristics of the disk provided
  38.  * by GETDPB.
  39.  */
  40.  
  41.  void
  42. SortDir (void) {
  43.     extern char     Disk, Parent[67], Element[13];
  44.     extern char     Line[80], Level, RSwt, VerSwt, Packed, TruncateSwt;
  45.     extern int      Lim, j, l;
  46.     extern int      OutSectors, OutClusters, BytesPerCluster, ECount;
  47.     extern int     *CluArray;
  48.     extern unsigned NumSec;
  49.     extern unsigned DirStart;
  50.     extern long     MinMem;
  51.     extern struct DpbStruct Dpb;
  52.     extern struct DirEntry *DirBuff;
  53.     extern struct ClusterEntry *p, *t;
  54.     extern struct ExtFcb Fcb;
  55.     extern struct ExtendedEntry Dir;
  56.     extern struct ClusterQueue CluQ;
  57.  
  58.     char           *strrspn();
  59.     char          **DirVector, *r;
  60.     int             strincmp();
  61.     int             i, k, DirCount, Root;
  62.     long            Mem;
  63.  
  64.     BytesPerCluster = (Dpb.ClusterSize + 1) * Dpb.SectorSize;
  65.     if (strlen(Element) != 0) {            /* Sorting a sub-directory */
  66.         Root = 0;
  67.         bdosptr(0x3B, Parent, 0);        /* Set Current Directory */
  68.         if ((Parent[strlen(Parent) - 1] != '\\') && (Parent[strlen(Parent) - 1] != '/'))
  69.             strcat(Parent, "\\");
  70.         setdta((char *) &Dir);
  71.         parsfnm(Element, (struct fcb *) & Fcb.DriveId, 0);
  72.         Fcb.FcbHdr.Header = 0xFF;
  73.         Fcb.DriveId = Disk - '@';
  74.         Fcb.FcbHdr.Attrib = 0xFF;
  75.         if (SearchFirst(&Fcb) != 0) {
  76.             fprintf(stderr, "Not found: %s%s\n", Parent, Element);
  77.             AbortProgram();
  78.             }
  79.         }
  80.     else Root = 1;                /* Sorting the Root directory */
  81.  
  82.     printf("Sorting: %s%s", Parent, Element);
  83.     if (!isdevice(1)) fprintf(stderr, "Sorting: %s%s", Parent, Element);
  84.  
  85.     /* Read directory to be sorted into memory */
  86.  
  87.     if (Root) ReadRoot();
  88.     else ReadSub();
  89.  
  90.     /* Count sub-directories, skipping "current" and "parent" entries */
  91.  
  92.     for (DirCount = 0, i = 0; i < Lim / sizeof(struct DirEntry); i++) {
  93.         if (DirBuff[i].Name[0] == 0) break;
  94.         if ((DirBuff[i].Attribute & 0x10)
  95.             && (DirBuff[i].Name[0] != '.')
  96.             && (DirBuff[i].Name[0] != 0xE5)) DirCount++;
  97.         }
  98.     k = i;
  99.     if (DirCount != 0) {
  100.         if ((DirVector = malloc(DirCount * sizeof(DirVector))) == NULL) {
  101.             fprintf(stderr, "Insufficient memory (2).\n");
  102.             return;
  103.             }
  104.         }
  105.  
  106.     j = 0;
  107.     if (Root) {
  108.  
  109.         /* If sorting Root - skip 1st two files if "System" & "Hidden" */
  110.  
  111.         if (i > 1) {
  112.             if (DirBuff[j].Attribute & 0x06) {
  113.                 j++;
  114.                 i--;
  115.                 if (DirBuff[j].Attribute & 0x06) {
  116.                     j++;
  117.                     i--;
  118.                     }
  119.                 }
  120.             }
  121.         }
  122.     else {
  123.  
  124.         /*
  125.          * If sorting subdirectory - skip 1st two entries, "current" and
  126.          * "parent"
  127.          */
  128.  
  129.         j += 2;
  130.         i -= 2;
  131.         }
  132.     if (i == 0) {
  133.         printf(" Empty.\n");
  134.         r = &Parent[strlen(Parent) - 1];
  135.         if (r[-1] == ':') r++;
  136.         *r = 0x00;
  137.         if (TruncateSwt) {
  138.             OutClusters = 1;
  139.             WriteSub();
  140.             }
  141.         return;
  142.         }
  143.  
  144.     /* If VerSwt ON - request operator confirmation BEFORE sorting */
  145.  
  146.     if (VerSwt != 0) {
  147.         if (isdevice(1)) {
  148.             printf("   Sort (Y or N)? ");
  149.             fflush(stdout);
  150.             }
  151.         else {
  152.             fprintf(stderr, "   Sort (Y or N)? ");
  153.             fflush(stderr);
  154.             }
  155.         if (toupper(getche()) != 'Y') {
  156.             if (!isdevice(1)) fprintf(stderr, "n");
  157.             printf("\n");
  158.             return;
  159.             }
  160.         }
  161.  
  162.     if (!isdevice(1)) fprintf(stderr, "\n");
  163.     printf("\n");
  164.  
  165.     /* Sort directory */
  166.  
  167.     qsort(&DirBuff[j], i, sizeof(struct DirEntry), strincmp);
  168.  
  169.     ECount = 0;
  170.  
  171.     /*
  172.      * If Packed OFF, remove "erased" entries from directory (mark them
  173.      * "unused)
  174.      */
  175.  
  176.     if (Packed != 0) {
  177.         for (i = k; i >= 0; i--) {
  178.             if ((DirBuff[i].Name[0] != 0xE5) && (DirBuff[i].Name[0] != 0x00)) break;
  179.             if (DirBuff[i].Name[0] == 0xE5) {
  180.                 DirBuff[i].Name[0] = 0x00;
  181.                 ++ECount;
  182.                 }
  183.             }
  184.         }
  185.  
  186.     if (TruncateSwt) {
  187.         for (i = k; i >= 0; --i) {
  188.             if (DirBuff[i].Name[0] != 0x00) break;
  189.             }
  190.         i += 2;
  191.         }
  192.  
  193.     /*
  194.      * Compute the number of directory sectors to write out - don't write
  195.      * sectors that don't contain active entries.
  196.      */
  197.  
  198.     OutSectors = ((i * 32) + Dpb.SectorSize - 1) / Dpb.SectorSize;
  199.     OutClusters = (OutSectors + Dpb.ClusterSize) >> Dpb.ClusterShift;
  200.  
  201.     /* Build list of subdirectories - skipping "current" and "parent" entries */
  202.  
  203.     for (l = 0, i = 0; DirBuff[i].Name[0]; i++) {
  204.         if ((DirBuff[i].Attribute & 0x10) && (DirBuff[i].Name[0] != '.')) {
  205.             for (k = 0, j = 0; j < 8; ++j) {
  206.                 if (DirBuff[i].Name[j] == ' ') break;
  207.                 else Line[k++] = DirBuff[i].Name[j];
  208.                 }
  209.             if (DirBuff[i].Ext[0] != ' ') {
  210.                 Line[k++] = '.';
  211.                 for (j = 0; j < 3; ++j) {
  212.                     if (DirBuff[i].Ext[j] == ' ') break;
  213.                     else Line[k++] = DirBuff[i].Ext[j];
  214.                     }
  215.                 }
  216.             Line[k++] = '\0';
  217.             if ((DirVector[l] = malloc(k)) == NULL) {
  218.                 fprintf(stderr, "Insufficient memory.\n");
  219.                 return;
  220.                 }
  221.             strcpy(DirVector[l++], Line);
  222.             }
  223.         }
  224.  
  225.     /* Write out sorted directory */
  226.  
  227.     if (Root) {
  228.         WriteRoot();
  229.         if (RSwt) printf("    Location: %04XH-%04XH\n", DirStart, DirStart + NumSec - 1);
  230.         }
  231.     else {
  232.         WriteSub();
  233.         if (RSwt) {
  234.             printf("    Location:");
  235.             for (i = 0; i < CluQ.Count; ++i) {
  236.                 if (i == 0) printf(" %04XH", Alu2Sec(&Dpb, CluArray[i]));
  237.                 if ((i > 0) && (CluArray[i] != CluArray[i - 1] + 1)) {
  238.                     printf("-%04XH %04XH",
  239.                            Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1,
  240.                            Alu2Sec(&Dpb, CluArray[i])
  241.                         );
  242.                     }
  243.                 }
  244.             printf("-%04XH\n", Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1);
  245.             }
  246.         }
  247.     if (RSwt) printf("    %d Erased entries removed\n", ECount);
  248.  
  249.     Mem = coreleft();
  250.     if (MinMem < Mem) MinMem = Mem;
  251.  
  252.     /* Release dynamically acquired space for this directory */
  253.  
  254.     free(DirBuff);
  255.     for (p = CluQ.Head; p != NULL; p = t) {
  256.         t = p->Next;
  257.         free(p);
  258.         }
  259.     free(CluArray);
  260.  
  261.     /*
  262.      * If Recursive sort - build Parent and Element for sub directories &
  263.      * sort
  264.      */
  265.  
  266.     if (!Level) {
  267.         strcat(Parent, Element);
  268.         for (i = 0; i < DirCount; i++) {
  269.             strcpy(Element, DirVector[i]);
  270.  
  271.             SortDir();
  272.  
  273.             }
  274.         r = strrspn(Parent, "\\/");
  275.         if (r[-1] == ':') r++;
  276.         *r = 0x00;
  277.         }
  278.     }
  279.  
  280.  void
  281. ReadSub (void) {
  282.     extern unsigned Cluster;
  283.     extern unsigned LastCluster;
  284.     extern unsigned char *Fat;
  285.     extern struct ExtendedEntry Dir;
  286.     extern struct ClusterQueue CluQ;
  287.     extern int      Is12Bit, *CluArray, BytesPerCluster, Lim;
  288.     extern char     Disk;
  289.     extern struct DirEntry *DirBuff;
  290.     extern struct DpbStruct Dpb;
  291.  
  292.     int             i;
  293.     struct ClusterEntry *p;
  294.     void            PutQueue();
  295.     unsigned        NextCl();
  296.  
  297.     Cluster = Dir.Body.FirstCluster;
  298.     CluQ.Head = CluQ.Current = NULL;
  299.     CluQ.Count = 0;
  300.     while (Cluster < LastCluster) {
  301.         PutQueue(&CluQ, Cluster);
  302.         Cluster = NextCl(Is12Bit, Cluster, Fat);
  303.         }
  304.     if ((CluArray = malloc(CluQ.Count * sizeof(int))) == NULL) {
  305.         fprintf(stderr, "Insufficient memory (3).\n");
  306.         return;
  307.         }
  308.     for (i = 0, p = CluQ.Head; p != NULL; i++, p = p->Next) {
  309.         CluArray[i] = p->Cluster;
  310.         }
  311.     Lim = CluQ.Count * BytesPerCluster;
  312.     if ((DirBuff = malloc(Lim)) == NULL) {
  313.         fprintf(stderr, "Insufficient memory for directory buffer.\n");
  314.         return;
  315.         }
  316.     for (i = 0; i < CluQ.Count; i++) {
  317.         if (absread(Disk - 'A', Dpb.ClusterSize + 1,
  318.                     Alu2Sec(&Dpb, CluArray[i]),
  319.                     (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  320.             fprintf(stderr, "Error reading directory.\n");
  321.             exit(1);
  322.             }
  323.         }
  324.     }
  325.  
  326.  void
  327. WriteSub (void) {
  328.     extern char     TruncateSwt;
  329.     extern unsigned char *Fat;
  330.     extern char     FatDirty;
  331.     extern struct ClusterQueue CluQ;
  332.     extern char     Disk;
  333.     extern struct DpbStruct Dpb;
  334.     extern int     Is12Bit, *CluArray, BytesPerCluster;
  335.     extern int      OutClusters;
  336.     extern struct DirEntry *DirBuff;
  337.  
  338.     int             i;
  339.  
  340.     for (i = 0; i < OutClusters; i++) {
  341.         if (abswrite(Disk - 'A', Dpb.ClusterSize + 1,
  342.                      Alu2Sec(&Dpb, CluArray[i]),
  343.                      (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  344.             fprintf(stderr, "Error writing directory.\n");
  345.             exit(1);
  346.             }
  347.         }
  348.     if ( (TruncateSwt) && (i < CluQ.Count) ) {
  349.         FatDirty |= 1;
  350.         FreeCluster(Is12Bit, 0xFFFF, CluArray[i - 1], Fat);
  351.         for (; i < CluQ.Count; ++i) FreeCluster(Is12Bit, 0, CluArray[i], Fat);
  352.         }
  353.     }
  354.  
  355.  void
  356. ReadRoot (void) {
  357.     extern struct DpbStruct Dpb;
  358.     extern unsigned NumSec;
  359.     extern unsigned DirStart;
  360.     extern struct DirEntry *DirBuff;
  361.     extern int     *CluArray, Lim;
  362.     extern char     Disk;
  363.  
  364.     int             Error;
  365.  
  366.     Lim = Dpb.MaxEntries * 32;
  367.     NumSec = (Lim + Dpb.SectorSize - 1) / Dpb.SectorSize;
  368.     if ((DirBuff = malloc(Lim)) == NULL) {
  369.         fprintf(stderr, "Insufficient memory for cluster buffer.\n");
  370.         return;
  371.         }
  372.     if ((CluArray = malloc(sizeof(int))) == NULL) {
  373.         fprintf(stderr, "Insufficient memory (4).\n");
  374.         return;
  375.         }
  376.     CluArray[0] = 0;
  377.     if ((Error = absread(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) != 0) {
  378.         fprintf(stderr, "Error reading root:  %04X.\n", Error);
  379.         exit(1);
  380.         }
  381.     }
  382.  
  383.  
  384.  void
  385. WriteRoot (void) {
  386.     extern char     Disk;
  387.     extern unsigned NumSec;
  388.     extern unsigned DirStart;
  389.     extern struct DpbStruct Dpb;
  390.     extern struct DirEntry *DirBuff;
  391.  
  392.     if (abswrite(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) {
  393.         fprintf(stderr, "Error writing Root.\n");
  394.         exit(1);
  395.         }
  396.     }
  397.